package com.example.contestsystem.Service;

import com.example.contestsystem.Dao.*;
import com.example.contestsystem.Entity.*;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class TeamService {
    final TeamRepository teamRepository;
    final JoinTeamRepository joinTeamRepository;
    final ContestRepository contestRepository;
    final SignUpContestRepository signUpContestRepository;
    final StudentRepository studentRepository;


    public TeamService(TeamRepository teamRepository, JoinTeamRepository joinTeamRepository,
                       ContestRepository contestRepository, SignUpContestRepository signUpContestRepository,
                       StudentRepository studentRepository) {
        this.contestRepository = contestRepository;
        this.teamRepository = teamRepository;
        this.joinTeamRepository = joinTeamRepository;
        this.signUpContestRepository = signUpContestRepository;
        this.studentRepository =studentRepository;
    }

    public boolean createTeam(Team team) {
        // 如果竞赛是个人赛，则没有创建队伍这一操作
        if(!isTeamContest(team.getContestId()))
            return false;
        // 如果在此竞赛中已有队伍，那么则不予创建新队伍
        if(checkDuplicateTeam(team.getContestId(), team.getCaptainAccount()))
            return false;

        String teamId = "team" + team.getCaptainAccount() + (new Date().hashCode());
        team.setTeamId(teamId);
        team.setTeamMemberNum(1);

        JoinTeam joinTeam = new JoinTeam();
        joinTeam.setContestId(team.getContestId());
        joinTeam.setStuAccount(team.getCaptainAccount());
        joinTeam.setTeamId(teamId);

        this.teamRepository.save(team);
        this.joinTeamRepository.save(joinTeam);
        return true;// 实际上这里应该再次查找作为检验
    }

    public boolean deleteTeam(String teamId) {
        this.joinTeamRepository.deleteByTeamId(teamId);
        this.teamRepository.deleteByTeamId(teamId);
        return this.teamRepository.findByTeamId(teamId) == null;
    }

    public boolean verifyCaptain(String teamId, int loginStuAccount) {
        Team team = this.teamRepository.findByTeamId(teamId);
        if(team!=null){
            return team.getCaptainAccount() == loginStuAccount;
        }else return false;
    }

    /**
     * 此方法需要被自动执行的竞赛方法调用
     * @param contestMemberMin 竞赛要求的最少成员数量
     */
    public void markInvalidTeams(String contestId, int contestMemberMin) {
        List<Team> teams = teamRepository.findByContestId(contestId); // 获取当前竞赛的所有小组
        for (Team team : teams) {
            if (team.getTeamMemberNum() < contestMemberMin) {
                team.setIsTeamValid(2); // 标记不达标的小组
            }
        }
    }

    public Team findByTeamId(String teamId){
        return this.teamRepository.findByTeamId(teamId);
    }


    public boolean checkDuplicateTeam(String contestId, int stuAccount){
        JoinTeam destinationTeam = this.joinTeamRepository.findByContestIdAndStuAccount(contestId, stuAccount);
        return destinationTeam != null;
    }

    public boolean isTeamContest(String contestId){
        Contest destinationContest = this.contestRepository.findByContestId(contestId);
        return destinationContest.getTeamMemberLimit() != 1;
    }

    public boolean isContestValid(String contestId){
        return this.contestRepository.findByContestId(contestId).getIsValid() == 0;
    }

    public boolean joinTeam(String teamId, int stuAccount){
        // 找到对应Team
        Team desTeam = this.teamRepository.findByTeamId(teamId);
        if(desTeam == null)
            return false;
        String desContestId = desTeam.getContestId();
        // 如果竞赛已经过期，则不予进行操作
        Contest desContest = this.contestRepository.findByContestId(desContestId);
        if(!isContestValid(desContestId))
            return false;
        // 如果没有参加比赛，则不予进行操作
        SignUpContest desSignUpContest = this.signUpContestRepository.findByContestIdAndStuAccount(desContestId, stuAccount);
        if(desSignUpContest == null)
            return false;
        // 如果已经在队伍中，则不予进行操作
        JoinTeam desJoinTeam = this.joinTeamRepository.findByTeamIdAndStuAccount(teamId, stuAccount);
        if(desJoinTeam != null)
            return false;

        if(desTeam.getTeamMemberNum()< desContest.getTeamMemberLimit()){
            JoinTeam joinTeam = new JoinTeam();
            joinTeam.setJoinId(new Date().hashCode());
            joinTeam.setTeamId(teamId);
            joinTeam.setContestId(desContestId);
            joinTeam.setStuAccount(stuAccount);
            this.teamRepository.incrementTeamMemberNum(teamId);
            this.joinTeamRepository.save(joinTeam);
            return true;
        }
        return false;
    }

    public List<Team> findByContestId(String contestId) {
        return this.teamRepository.findByContestId(contestId);
    }

    public PageImpl<Team> findByContestId(String contestId, int pageIndex, int pageSize) {
        Pageable pageable = PageRequest.of(pageIndex, pageSize);
        List<Team> teams = this.teamRepository.findByContestId(contestId);
        return new PageImpl<>(teams, pageable, teams.size());
    }

    /**
     * 此方法实现在某个竞赛来查看自己的队伍的基本信息
     */
    public Team findByStuAccountAndContestId(int stuAccount, String contestId){
        JoinTeam joinTeam = this.joinTeamRepository.findByContestIdAndStuAccount(contestId, stuAccount);
        if(joinTeam != null)
            return this.teamRepository.findByTeamId(joinTeam.getTeamId());
        return null;
    }

    /**
     * 此方法实现查看某个队伍的成员
     */
    public List<Student> findMember(String teamId){
        List<JoinTeam> joinTeamList = this.joinTeamRepository.findByTeamId(teamId);
        List<Student> students = new ArrayList<>();
        for (JoinTeam joinTeam: joinTeamList){
            students.add(this.studentRepository.findByStuAccount(joinTeam.getStuAccount()));
        }
        return students;
    }

    public  List<Team> findByStuAccount(int stuAccount){
        List<JoinTeam> joinTeamList = this.joinTeamRepository.findByStuAccount(stuAccount);
        List<Team> teamList = new ArrayList<>();
        for(JoinTeam joinTeam: joinTeamList){
            teamList.add(this.teamRepository.findByTeamId(joinTeam.getTeamId()));
        }
        return teamList;
    }

    public Page<Team> findByStuAccount(int stuAccount, int pageIndex, int pageSize){
        Pageable pageable = PageRequest.of(pageIndex, pageSize);
        List<JoinTeam> joinTeamList = this.joinTeamRepository.findByStuAccount(stuAccount);
        List<Team> teams = new ArrayList<>();
        for(JoinTeam joinTeam: joinTeamList){
            teams.add(this.teamRepository.findTeamByContestId(joinTeam.getContestId()));
        }
        return new PageImpl<>(teams, pageable, teams.size());
    }

    public Page<Student> findByTeamId(String teamId, int pageIndex, int pageSize){
        Pageable pageable = PageRequest.of(pageIndex, pageSize);
        List<JoinTeam> joinTeamList = this.joinTeamRepository.findByTeamId(teamId);
        List<Student> students = new ArrayList<>();
        for(JoinTeam joinTeam: joinTeamList){
            students.add(this.studentRepository.findByStuAccount(joinTeam.getStuAccount()));
        }
        return new PageImpl<>(students, pageable, students.size());
    }
}
